#include "datautils.h"
#include "dataparse.h"

#include <QString>
#include <QUrlQuery>
#include <QJsonArray>
#include <QJsonDocument>
#include <QNetworkRequest>
#include <QJsonParseError>

DataParse::DataParse(QObject *parent) : QObject{parent} {
    // 创建网络管理器
    m_Future = new QNetworkAccessManager(this);
    m_Current = new QNetworkAccessManager(this);

    // 管理器信号和数据处理槽函数连接
    connect(m_Future, &QNetworkAccessManager::finished, this, &DataParse::futureReply);
    connect(m_Current, &QNetworkAccessManager::finished, this, &DataParse::currentReply);
}

// 调用天气数据获取接口
void DataParse::getWeatherInfo(const QString &city) {
    getWeatherData(city, Future);
    getWeatherData(city, Current);
}

QUrl DataParse::buildCommonUrl(const QString &city, RequestType type) const {
    QUrl url("https://weather.visualcrossing.com/VisualCrossingWebServices/rest/services/timeline/"
             + QUrl::toPercentEncoding(city));

    QUrlQuery query;
    query.addQueryItem("unitGroup", "metric");
    query.addQueryItem("key", m_apiKey);        // 添加个人密钥
    query.addQueryItem("lang", "zh");           // 部分翻译成中文（可选）

    switch (type) {
    case Future :
        query.addQueryItem("include", "days");
        query.addQueryItem("elements", "datetime,conditions,tempmax,tempmin,temp,winddir,windspeed,humidity,icon");
        break;
    case Current:
        query.addQueryItem("elements", "datetime,pm2p5");
        break;
    }

    url.setQuery(query);
    return url;
}

void DataParse::getWeatherData(const QString &city, RequestType type) {
    QNetworkRequest request(buildCommonUrl(city, type));
    request.setRawHeader("Accept", "application/json");

    // 根据类型选择不同QNetworkAccessManager对象
    (type == Future ? m_Future : m_Current)->get(request);
}

// 七日数据获取
void DataParse::futureReply(QNetworkReply *reply) {
    if (reply->error() != QNetworkReply::NoError) {
        const QString errorMsg = QString("七日信息获取 网络错误: %1 (%2)").arg(reply->errorString()).arg(reply->error());
        emit errorOccurred(errorMsg);
        reply->deleteLater();
        return ;
    }

    const int statusCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
    if (statusCode != 200) {
        emit errorOccurred(QString("七日信息获取 HTTP错误码: %1").arg(statusCode));
        reply->deleteLater();
        return ;
    }

    // 读取数据
    const QByteArray rawData = reply->readAll();
    if (rawData.isEmpty()) {
        emit errorOccurred("七日信息获取 接收到空数据响应");
        reply->deleteLater();
        return ;
    }

    // 打印原始数据
    // qDebug().nospace() << QString::fromUtf8(rawData);

    parseFutureData(rawData);
    reply->deleteLater();
}

// 当日空气信息获取
void DataParse::currentReply(QNetworkReply *reply) {
    if (reply->error() != QNetworkReply::NoError) {
        const QString errorMsg = QString("当日信息获取 网络错误: %1 (%2)").arg(reply->errorString()).arg(reply->error());
        emit errorOccurred(errorMsg);
        reply->deleteLater();
        return ;
    }

    const int statusCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
    if (statusCode != 200) {
        emit errorOccurred(QString("当日信息获取 HTTP错误码: %1").arg(statusCode));
        reply->deleteLater();
        return ;
    }

    // 读取数据
    const QByteArray rawData = reply->readAll();
    if (rawData.isEmpty()) {
        emit errorOccurred("当日信息获取 接收到空数据响应");
        reply->deleteLater();
        return ;
    }

    // 打印原始数据
    // qDebug().nospace() << QString::fromUtf8(rawData);

    parseCurrentData(rawData);
    reply->deleteLater();
}

// 七日天气信息解析
void DataParse::parseFutureData(const QByteArray &data) {
    auto emitError = [this](const QString& msg) { emit errorOccurred(msg); };

    QJsonParseError jsonError;
    auto doc = QJsonDocument::fromJson(data, &jsonError);
    if (jsonError.error != QJsonParseError::NoError)
        return emitError("JSON错误: " + jsonError.errorString());

    const auto root = doc.object();
    if (root.isEmpty())
        return emitError("无效的根对象");

    // 关键字段快速验证
    const auto validate = [&](const QString& key, QJsonValue::Type type) {
        return root.contains(key) && root[key].type() == type;
    };

    if (!validate("days", QJsonValue::Array) || !validate("timezone", QJsonValue::String))
        return emitError("缺失必要字段");

    QVector<FutureDays> futuredays;

    QString timezone = root["timezone"].toString();

    // 解析所有天气信息
    QJsonArray days = root["days"].toArray();
    for (int i = 0; i < days.size() && i < 7; ++i) {
        QJsonObject dayObj = days[i].toObject();
        FutureDays day;

        day.date = dayObj["datetime"].toString();
        day.week = DateUtils::dateToWeek(day.date, timezone);
        day.tempHigh = qRound(dayObj["tempmax"].toDouble());
        day.tempLow = qRound(dayObj["tempmin"].toDouble());
        day.averageTemp = qRound(dayObj["temp"].toDouble());
        day.humidity = qRound(dayObj["humidity"].toDouble());
        day.windPower = WindUtils::windLevelString(dayObj["windspeed"].toDouble());
        day.windDirection = WindUtils::degreeToDirection(dayObj["winddir"].toDouble());
        day.weatherType = dayObj["conditions"].toString()
                              .split(',', Qt::SkipEmptyParts).value(0, "").trimmed();
        day.iconType = IconUtils::getIconPath( dayObj["icon"].toString().toLower());

        futuredays.append(day);
    }

    if (futuredays.isEmpty()) {
        emitError("无有效天气数据");
    } else {
        qDebug() << "解析到有效七天数据";
        emit FutureInfoReady(futuredays);
    }
}

// 当日空气质量信息解析
void DataParse::parseCurrentData(const QByteArray &data) {
    QJsonParseError error;
    QJsonDocument doc = QJsonDocument::fromJson(data, &error);
    if (error.error != QJsonParseError::NoError) {
        emit errorOccurred("JSON解析错误: " + error.errorString());
        return;
    }

    QJsonObject root = doc.object();
    QJsonArray days = root["days"].toArray();

    QJsonObject todayObj = days[0].toObject();
    CurrentDay today;
    QString cityName = root["resolvedAddress"].toString().split(',').first().trimmed();
    today.city = CityConverter::toChinese(cityName);
    today.pm25 = todayObj["pm2p5"].toInt();
    today.calculateAirQuality();

    qDebug() << "解析到有效当日数据";
    emit CurrentInfoReady(today);
}
